
#include <stdatomic.h>
#include <sys/types.h>
#include <unistd.h>
#include "queue.c"

typedef struct __lock_t {
	atomic_flag flag;
	queue_t *wait_queue;
} lock_t;

void init(lock_t *mutex) {
	queue_init(mutex->wait_queue);
}

void lock(lock_t *mutex) {
	while (atomic_flag_test_and_set(&flag)) 
	; // spin

	if (!queue_empty(mutex->wait_queue)) {
		// 将当前线程放入到队列中
		queue_add(mutex->queue, gettid());

		atomic_flag_clear(&flag);
		// 伪代码，阻塞当前线程，需要发起一次系统调用
		park();
	} else {
		atomic_flag_clear(&flag);
	}
}

void unlock(lock_t *mutex) {	
	while (atomic_flag_test_and_set(&flag))
    ; // spin
	
	if (!queue_empty(mutex->wait_queue)) {
		// 伪代码，唤醒队列中的一个线程，需要发起系统调用
		unpark(queue_remove(mutex->wait_queue)); // hold lock
	}

	atomic_flag_clear(&flag);
}

